using System;
using System.Collections;
using System.Data.Linq.Mapping;
using System.Runtime.Serialization;
using System.Transactions;
using Portal.Data.Helper;
using Portal.Core;
using Portal.Core.Binding.FormBuilder;
using Portal.Core.Helper;
using System.Linq;

namespace Portal.Data.Entity
{
    [Table(Name = "dbo.Comment"), Serializable, DataContractAttribute]
    public class Comment : BaseObject
    {
        #region Properties
        [SkipBinding]
        [ColumnAttribute(Name = "Id", IsPrimaryKey = true, IsDbGenerated = true)]        
        public int ID { get; set; }

        [ColumnAttribute(Name = "ContentId")]
        public int ContentId { get; set; }

        [ColumnAttribute(Name = "Title")]
        public string Title { get; set; }

        [ColumnAttribute(Name = "Address")]
        public string Address { get; set; }

        [ColumnAttribute(Name = "FullName")]
        public string FullName { get; set; }

        [ColumnAttribute(Name = "Email")]
        public string Email { get; set; }

        [ColumnAttribute(Name = "Body")]
        public string Body { get; set; }

        [ColumnAttribute(Name = "SentDate")]
        public DateTime? SentDate { get; set; }

        [ColumnAttribute(Name = "ModifiedDate")]
        public DateTime? ModifiedDate { get; set; }

        [ColumnAttribute(Name = "ModifiedBy")]
        public int? ModifiedBy { get; set; }

        [ColumnAttribute(Name = "Status")]
        public int? Status { get; set; }

        [ColumnAttribute(Name = "LikeCount")]
        public int? LikeCount { get; set; }

        [ColumnAttribute(Name = "LikeTime")]
        public DateTime? LikeTime { get; set; }

        [ColumnAttribute(Name = "IsReply")]
        public bool? IsReply { get; set; }


        #endregion

        #region Methods
        public static Comment FindByPrimaryKey(object objectid)
        {
            return FindByPrimaryKey<Comment>(objectid);
        }
        public static IList Search(CommentSearch cs, int pagesize, int pageindex, out int count)
        {
            count = 0;
            if (cs == null) return new ArrayList();

            //getcache  -----------------------
            var parameter = new object[] { typeof(Comment).Name, "Search", cs.ToString(), pageindex };
            var obj = CacheHelper.Instance.Get(parameter);
            if (obj != null)
            {
                var values = (object[])obj;
                count = (int)values[1];
                return (IList)values[0];
            }
            string sql = "select o.* from Comment o where o.ID>0";
            if (cs.FromDate != DateTime.MinValue)
            {
                sql += " and o.SentDate>='" + cs.FromDate + "'";
            }
            if (cs.ToDate != DateTime.MinValue)
            {
                sql += " and o.SentDate<='" + cs.ToDate.ToString(Const.SqlDateFull) + "'";
            }
            if (cs.ContentId > 0)
            {
                sql += " and o.ContentId=" + cs.ContentId;
            }
            if (cs.IsCorrectStatus)
            {
                sql += " and o.Status=" + (int)cs.Status;
            }

            const string orderbyClause = " order by o.ID desc, o.ContentId asc";

            var list = LINQHelper.SlicedFindAll<Comment>(sql, orderbyClause, pageindex * pagesize, pagesize, out count);
            var newvalues = new object[] { list, count };
            CacheHelper.Instance.Set(parameter, newvalues);
            return list;
        }
        public static int CountByStatus(int contentId, object status = null)
        {
            //getcache  -----------------------
            var parameter = new[] { typeof(Comment).Name, "CountByStatus", contentId, status };
            var obj = CacheHelper.Instance.Get(parameter);
            if (obj == null)
            {
                int result;
                 //fix bug: using NOLOCK to ignore transaction deadlock
                using (var t = new TransactionScope(TransactionScopeOption.Required,
                    new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }))
                {
                    using (var context = new CmsDataContext())
                    {
                        result = status == null
                                     ? context.Comments.Where(o => o.ContentId == contentId).Count()
                                     : context.Comments.Where(o => o.ContentId == contentId && o.Status == (int) status)
                                           .
                                           Count();
                        t.Complete();
                    }
                }
                CacheHelper.Instance.Set(parameter, result);
                return result;
            }
            return (int)obj;
        }
        #endregion Methods

        #region LOGIC
        public static void RecachingCounter(int contentId, object status)
        {
            var parameter = new object[] { "CountByStatus", contentId, status };
            CacheHelper.Instance.Set(parameter, null);    //clear old data
            CountByStatus(contentId, status);   //create new value
        }
        #endregion
    }

    public class CommentSearch
    {
        public string Key { get; set; }
        public bool IsCorrectWords { get; set; }

        public DateTime FromDate { get; set; }

        public DateTime ToDate { get; set; }

        public int ContentId { get; set; }

        public bool IsCorrectStatus { get; set; }
        public ObjectStatusClass.CommonStatus Status { get; set; }

        private const string FormatDate = "yyyyMMdd, ";
        public override string ToString()
        {
            var s = Key + IsCorrectWords + ContentId + IsCorrectStatus + FromDate.ToString(FormatDate) + ToDate.ToString(FormatDate);
            s += (int)Status;
            return s;
        }
    }
}
